import {Layer} from "./Layer";
import {FeatureCollection, point} from "@turf/helpers";
import {TextStyle} from "./style/TextStyle";
import {CanvasTexture, SpriteMaterial, Sprite, Mesh, MeshBasicMaterial, Color, Group, LinearFilter} from "three";
import {centerOfMass} from '@turf/turf'
import {Point} from '@turf/helpers'
import {FreeMap, LatLng} from "../";
import {Filter} from "./filter/Filter";
import {Event} from 'three'
import {Properties} from "@turf/helpers/lib/geojson";

export class TextLayer extends Layer {

    public style: TextStyle;

    public filter: Filter;

    constructor(layerId: string, sourceId: string) {
        super(layerId, sourceId);

        this.style = new TextStyle();
        this.style.rectHeight = 20;
        this.style.rectWidth = 60;
        this.style.textColor = new Color('black');
        this.style.textSize = 10;
    }

    public addTo(map: FreeMap): void {
        super.addTo(map);
    }

    protected createCanvasContext(canvas: HTMLCanvasElement): CanvasRenderingContext2D {
        let context = canvas.getContext("2d");
        context.textAlign = "center";
        context.textBaseline = 'middle';
        context.fillStyle = this.style.textColor.getStyle();
        context.strokeStyle = this.style.textColor.getStyle();
        context.font = `${this.style.textSize}px -apple-system, BlinkMacSystemFont,
         "Helvetica Neue", "PingFang SC", "Microsoft YaHei", "Source Han Sans SC",
          "Noto Sans CJK SC", "WenQuanYi Micro Hei", sans-serif`;

        return context;
    }

    protected createTextCanvas(): HTMLCanvasElement {
        let canvas = document.createElement('canvas');
        canvas.width = this.style.rectWidth;
        canvas.height = this.style.rectHeight;

        return canvas
    }

    protected createTextSprite(text: string, center: Point): Sprite {
        let canvas = this.createTextCanvas();

        let context = this.createCanvasContext(canvas);

        let centerVec = this.map.mapRenderer.camera.projection(
            new LatLng(center.coordinates[1], center.coordinates[0]));

        let resolution = this.map.mapRenderer.camera.getResolution();

        context.fillText(text, canvas.width / 2, canvas.height / 2,
            canvas.width);
        let textWidth = context.measureText(text).width;

        let spriteTexture = new CanvasTexture(canvas);
        spriteTexture.minFilter = LinearFilter;

        let spriteMaterial = new SpriteMaterial({
            map: spriteTexture
        });

        let sprite = new Sprite(spriteMaterial);
        sprite.scale.set(resolution * this.style.rectWidth,
            resolution * this.style.rectHeight, 1.0);
        sprite.position.set(centerVec.x, centerVec.y, 0);
        sprite.userData.rectWidth = this.style.rectWidth;
        sprite.userData.rectHeight = this.style.rectHeight;

        return sprite;
    }

    onSourceDataChange(features: FeatureCollection): void {
        let sprites: Array<Sprite> = [];

        features.features
            .filter(feature => {
                return this.filter ? this.filter.filter(feature) : true;
            })
            .forEach(future => {
                let geometry = future.geometry;
                let properties = future.properties;
                let center = centerOfMass(future.geometry);

                if (this.style.textSelector in properties) {
                    let text = properties[this.style.textSelector];
                    sprites.push(this.createTextSprite(text, center.geometry));
                }
            });

        this.map.mapRenderer.scene.addSpriteLayer(this.layerId,sprites);
    }
}
